#include "digplan.hh"
#include <iostream>
#include <algorithm>
#include <optional>

static int hexValue(char ch)
{
    if (ch >= '0' && ch <= '9') return ch - '0';
    if (ch >= 'a' && ch <= 'f') return ch - 'a' + 10;
    exit(1);
}

DigPlan::DigPlan(const std::string& line) :
    direction{DigDirection::Down}, distance{-1}, color{}
{
    // First charcater is 'DigDirection'
    switch (line.front())
    {
    case 'U': this->direction = DigDirection::Up; break;
    case 'D': this->direction = DigDirection::Down; break;
    case 'L': this->direction = DigDirection::Left; break;
    case 'R': this->direction = DigDirection::Right; break;
    default: exit(1);
    }

    // Jump a space, line[2] is begin of distance, find next space
    std::size_t pos{3};
    while (line[pos] != ' ')
        pos += 1;
    
    // Parse str
    this->distance = std::atoi(&(line[2]));

    // line[pos] is ' ', line[pos + 1] must be a '('
    // So rgb value begin with line[pos + 3]
    auto getRGB = [&line] (std::size_t pos) -> int {
        return static_cast<int>(
            hexValue(line[pos]) * 16 + hexValue(line[pos + 1])
        );
    };
    pos += 3;
    this->color.red =   getRGB(pos);
    this->color.green = getRGB(pos + 2);
    this->color.blue =  getRGB(pos + 4);
}

void DigPlan::print() const
{
    // L 2 (#363e62)
    char dir {'\0'};
    switch (this->direction)
    {
    case DigDirection::Down:  dir = 'D'; break;
    case DigDirection::Up:    dir = 'U'; break;
    case DigDirection::Left:  dir = 'L'; break;
    case DigDirection::Right: dir = 'R'; break;
    }

    std::printf(
        "%c %d (#%02x%02x%02x)",
        dir,
        this->distance,
        this->color.red, 
        this->color.green,   
        this->color.blue
    );
}

/*

#######
#.....#
###...#
..#...#
..#...#
###.###
#...#..
##..###
.#....#
.######

*/
// void digInterior(std::vector<std::string>& digResult)
// {
//     // '#' => dig, '.' => unsure, '*' => Not dig
//     std::size_t rowSize {digResult.size()};
//     std::size_t colSize {digResult.front().size()};

//     for (std::size_t row = 0; row < rowSize; ++row)
//     {
//         for (std::size_t col = 0; col < colSize; ++col)
//         {
//             if (digResult[row][col] == '.')
//                 digInteriorOrExterior(digResult, row, col);
//         }
//     }
// }

// static void doDig(
//             std::vector<std::string>& digResult, 
//             std::size_t row, 
//             std::size_t col,
//             bool& interior
// )
// {   
//     if (digResult[row][col] != '.') return;

//     std::size_t rowSize {digResult.size()};
//     std::size_t colSize {digResult.front().size()};

//     digResult[row][col] = '@';
    
//     if (row != 0) doDig(digResult, row - 1, col, interior);
//     else interior = false;
    
//     if (row != rowSize - 1) doDig(digResult, row + 1, col, interior);
//     else interior = false;

//     if (col != 0) doDig(digResult, row, col - 1, interior);
//     else interior = false;

//     if (col != colSize - 1) doDig(digResult, row, col + 1, interior);
//     else interior = false;
// }

// static void digInteriorOrExterior(
//             std::vector<std::string>& digResult, 
//             std::size_t row, 
//             std::size_t col
// )
// {
//     // '@' => dig
//     bool interior {true};
//     doDig(digResult, row, col, interior);

//     char target { interior ? '#' : '*' };

//     std::size_t rowSize {digResult.size()};
//     std::size_t colSize {digResult.front().size()};

//     for (std::size_t row = 0; row < rowSize; ++row)
//     {
//         for (std::size_t col = 0; col < colSize; ++col)
//         {
//             if (digResult[row][col] == '@')
//                 digResult[row][col] = target;
//         }
//     }
// }

// std::size_t lavaSize(const std::vector<std::string>& digResult)
// {
//     std::size_t size {0};

//     std::size_t rowSize {digResult.size()};
//     std::size_t colSize {digResult.front().size()};

//     for (std::size_t row = 0; row < rowSize; ++row)
//     {
//         for (std::size_t col = 0; col < colSize; ++col)
//         {
//             if (digResult[row][col] == '#') size += 1;
//         }
//     }

//     return size;
// }